<?php

namespace common\models\db;

use fztadmin\behaviors\RBAC;
use wodrow\yii\rest\models\Route;
use wodrow\yii2wtools\tools\Tree;
use Yii;
use wodrow\yii2wtools\tools\ArrayHelper;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;

/**
 * This is the model class for table "{{%admin_power}}".
 *
 * @author
 * @property-read array $statusDesc
 * @property AdminPower $p
 * @property AdminPower[] $childrens
 */
class AdminPower extends \common\models\db\tables\AdminPower
{
    const SCENARIO_TEST = 'test';
    const STATUS_ACTIVE = 10;
    const TYPE_MENU = 1;
    const TYPE_FUN = 2;

    public $isChecked = 0;

    public function getStatusDesc()
    {
        return [
            self::STATUS_ACTIVE => "正常",
        ];
    }

    public function getTypeDesc()
    {
        return [
            self::TYPE_MENU => "菜单",
            self::TYPE_FUN => "方法",
        ];
    }

    public static function getAllRoutes()
    {
        $routes = [];
        foreach ((new Route())->getRoutes() as $k => $v) {
            if (strpos($k, '*')===false){
                $routes[] = $k;
            }
        }
        return $routes;
    }

    /**
     * @return AdminPower[]
     */
    public static function getAllPowers($checkCustom = 0)
    {
        if (Yii::$app->user->isGuest){}else{
            /**
             * @var User $user
             */
            $user = Yii::$app->user->identity;
            $custom = $user->custom;
        }
        $list = static::find()->all();
        $l1 = [];
        foreach ($list as $k => $v) {
            if (!$custom && $checkCustom){
                if (in_array($v->route, RBAC::$mustHasCustomUseRoutes)){
                    continue;
                }
            }
            $l1[] = $v;
        }
        return $l1;
    }

    /**
     * @return array
     */
    public static function getAllPowerArr()
    {
        $list = [];
        foreach (static::getAllPowers() as $k => $v) {
            $list[] = $v->toArray();
        }
        return $list;
    }

    /**
     * @return AdminPower[]
     */
    public static function getAllTypeList($type, $checkCustom = 0)
    {
        $list = [];
        foreach (static::getAllPowers($checkCustom) as $k => $v) {
            if ($v->type == $type)$list[] = $v;
        }
        return $list;
    }

    /**
     * @return array
     */
    public static function getAllPowerRoutes()
    {
        $routes = [];
        foreach (static::getAllPowers() as $k => $v){
            $routes[] = $v->route;
        }
        return $routes;
    }

    public static function generateMenuFunTree($menus, $funs)
    {
        $list = [];
        foreach ($menus as $k => $v) {
            $menu = is_array($v)?$v:$v->toArray();
            $menu['funs'] = [];
            foreach ($funs as $k1 => $v1){
                $fun = is_array($v1)?$v1:$v1->toArray();
                if ($v1->pid == $v->id){
                    $menu['funs'][] = $fun;
                }
            }
            $list[] = $menu;
        }
        $menuList = [
            ['id' => 0, 'pid' => null, 'label' => '操作菜单', 'options' => ['class' => 'header'], 'visible' => YII_ENV_DEV],
            ['id' => -1, 'pid' => null, 'label' => 'Gii', 'icon' => 'file-code-o', 'url' => ['/gii'], 'visible' => YII_ENV_DEV],
            ['id' => -2, 'pid' => null, 'label' => 'Debug', 'icon' => 'dashboard', 'url' => ['/debug'], 'visible' => YII_ENV_DEV],
        ];
        foreach ($list as $k => $v) {
            $menu = $v;
            $menu['label'] = $v['name'];
            $menu['url'] = [$v['route']];
            $menu['isChecked'] = $v['isChecked']??0;
            $menuList[] = $menu;
        }
        $menuTree = Tree::list2tree($menuList, null, 'id', 'pid', 'items');
        return $menuTree;
    }

    public static function getAdminMenuFunTree($checkCustom = 0)
    {
        $menus = static::getAllTypeList(static::TYPE_MENU, $checkCustom);
        $funs = static::getAllTypeList(static::TYPE_FUN, $checkCustom);
        return static::generateMenuFunTree($menus, $funs);
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors = ArrayHelper::merge($behaviors, [
            'timestamp' => [
                'class' => TimestampBehavior::class,
            ],
            'blameable' => [
                'class' => BlameableBehavior::class,
            ],
        ]);
        return $behaviors;
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios = ArrayHelper::merge($scenarios, [
            self::SCENARIO_TEST => [],
        ]);
        return $scenarios;
    }

    public function rules()
    {
        $rules = parent::rules();
        foreach ($rules as $k => $v) {
            if ($v[1] == 'required'){
                $rules[$k][0] = array_diff($rules[$k][0], ['created_at', 'updated_at', 'created_by', 'updated_by']);
            }
        }
        $rules = ArrayHelper::merge($rules, [
//            [[], 'required', 'on' => self::SCENARIO_TEST],
            [['pid'], 'validateLoop'],
        ]);
        return $rules;
    }

    public function validateLoop($attribute, $params)
    {
        $id = $this->id;
        $p = static::findOne($this->$attribute);
        if ($p){
            if ($p->id == $id){
                $this->addError($attribute, "产生闭环");
            }else{
                $p->validateLoop($attribute, $params);
            }
        }
    }

    public function attributeLabels()
    {
        $attributeLabels = parent::attributeLabels();
        $attributeLabels = ArrayHelper::merge($attributeLabels, [
            'pid' => "父级",
            'sort' => "排序",
            'type' => "类型",
            'status' => "状态",
        ]);
        return $attributeLabels;
    }

    public function beforeValidate()
    {
        if (parent::beforeValidate()){
            // TODO: Change the autogenerated stub
            return true;
        }else{
            return false;
        }
    }

    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)){
            if (!$insert)$this->generatePath();
            return true;
        }else{
            return false;
        }
    }

    public function beforeDelete()
    {
        if (parent::beforeDelete()){
            if ($this->childrens){
                return false;
            }
            return true;
        }else{
            return false;
        }
    }

    public function afterFind()
    {
        parent::afterFind();
        // TODO: Change the autogenerated stub
    }

    public function afterSave($insert, $changedAttributes)
    {
        parent::afterSave($insert, $changedAttributes);
        if ($insert){
            $this->generatePath();
            $this->save();
        }
        $this->_deleteCaches();
    }

    public function afterValidate()
    {
        parent::afterValidate();
        // TODO: Change the autogenerated stub
    }

    public function afterRefresh()
    {
        parent::afterRefresh();
        // TODO: Change the autogenerated stub
        $this->_deleteCaches();
    }

    public function afterDelete()
    {
        parent::afterDelete();
        AdminRolePower::deleteAll(['admin_power_id' => $this->id]);
        $this->_deleteCaches();
    }

    protected function _deleteCaches()
    {}

    public function test()
    {
        $test = self::instance();
        $test->setScenario(self::SCENARIO_TEST);
        $test->save();
        var_dump($test->toArray());
    }

    public function generatePath()
    {
        $this->path = (string)$this->id;
        if ($this->p){
            $this->path = $this->p->generatePath()."-".$this->path;
        }
        return $this->path;
    }

    public function getP()
    {
        return $this->hasOne(static::class, ['id' => 'pid']);
    }

    public function getChildrens()
    {
        return $this->hasMany(static::class, ['pid' => 'id']);
    }
}
